package mr.go.yaxc.actions;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import mr.go.yaxc.Action;
import mr.go.yaxc.ScopeHandler;

import org.xml.sax.Attributes;

/**
 * This action creates a map which it passes to parent's <i>params</i> (if
 * present), or, if <i>id</i> attribute is set, puts it in the global context.
 * For simplified map entries creation see how to combine this action with
 * {@link CreateMapEntry}
 * 
 * <h6>on xml element start:</h6> creates a new, empty map, which is set as
 * <i>object</i>. If <i>id</i> attribute is set map is put in global context. If
 * parent's <i>params</i> are present this map is added to them. Also sets
 * <i>property</i> 'map' with a value of this map <h6>on xml element end:</h6>
 * nothing <h6>
 * prerequisites:</h6> none <h6>
 * attributes:</h6>
 * <table>
 * <tr>
 * <th>Attribute name</th>
 * <th>What is it for?</th>
 * <th>Required?</th>
 * </tr>
 * <tr>
 * <td><i>id</i></td>
 * <td>if set, puts created map in global context</td>
 * <td>no</td>
 * </tr>
 * </tr>
 * <tr>
 * <td><i>ordered</i></td>
 * <td>if set with value of 'true', creates a map which preserves entries
 * ordering</td>
 * <td>no</td>
 * </tr>
 * </table>
 *<p>
 * Example:<br>
 * 
 * <pre>
 * &lt;Map&gt;
 * 				&lt;Entry&gt;
 * 					&lt;String&gt;name1&lt;/String&gt;
 * 					&lt;Integer&gt;0&lt;/Integer&gt;
 * 				&lt;/Entry&gt;
 * 				&lt;Entry&gt;
 * 					&lt;String&gt;name2&lt;/String&gt;
 * 					&lt;Integer&gt;1&lt;/Integer&gt;
 * 				&lt;/Entry&gt;
 * 			&lt;/Map&gt;
 * </pre>
 * 
 * @author Marcin Rzeźnicki
 * 
 */
public class CreateMap extends Action {

    @Override
    public void carryOut(String name, Attributes attributes,
                         ScopeHandler handler)
            throws Exception {
        boolean ordered = false;
        String orderedAttr = attributes.getValue(getAttribute("ordered"));
        if (orderedAttr != null) {
            ordered = Boolean.valueOf(orderedAttr);
        }
        Map<Object, Object> map;
        if (ordered) {
            map = new LinkedHashMap<Object, Object>();
        } else {
            map = new HashMap<Object, Object>();
        }
        object = map;
        String id = attributes.getValue("id");
        if (id != null) {
            handler.setReference(id,
                                 object);
            if (handler.getLogger().isDebugEnabled()) {
                handler.getLogger().debug("Id '{}': {}",
                                          id,
                                          map.toString());
            }
        }
        properties = new HashMap<String, Object>();
        properties.put("map",
                       map);
        handler.tryAddParam(map);
    }

    @Override
    public void processed(String body, ScopeHandler handler)
            throws Exception {
    }
}
